#define  _CRT_SECURE_NO_WARNINGS
#ifndef __MY_CLOUD__
#define __MY_CLOUD__
#include "data.hpp"
#include "httplib.h"
#include <windows.h>

namespace cloud
{
// 服务器IP地址与端口号
#define SERVER_ADDR "47.109.84.118"
// #define SERVER_ADDR "172.18.8.69"
#define SERVER_PORT 9090
	class Backup
	{
	private:
		std::string _back_dir;
		DataManager* _data;
	public:
		Backup(const std::string& back_dir, const std::string& back_file):
			_back_dir(back_dir)
		{
			_data = new DataManager(back_file);
		}
		
		// 获取文件唯一标识
		std::string GetFileIdentifier(const std::string& filename)
		{
			// a.txt-fsize-mtime
			FileUtil fu(filename);
			std::stringstream ss;
			ss << fu.FileName() << "-" << fu.FileSize() << "-" << fu.LastMTime();
			return ss.str();
		}
		
		// 上传文件
		bool Upload(const std::string& filename)
		{
			// 获取文件数据
			FileUtil fu(filename);
			std::string body;
			fu.GetContent(&body);

			// 搭建http客户端上传文件数据
			httplib::Client client(SERVER_ADDR, SERVER_PORT);
			httplib::MultipartFormData item;//表单，用于上传数据
			item.content = body;
			item.filename = fu.FileName();
			item.name = "file";// 表单字段
			item.content_type = "application/octet-stream";
			httplib::MultipartFormDataItems items;//表单数组:用于存储所有要上传的表单数据
			items.push_back(item);
			auto res = client.Post("/Upload", items);//发送一个POST请求到服务器的/upload路径，上传文件
			if (!res || res->status != 200)
			{
				std::cout << res->status << std::endl;
				return false;
			}
			return true;
		}

		// 判断是否需要上传文件
		bool IsNeedUpload(const std::string& filename)
		{
			// 需要上传的文件的判断条件：文件是新增的，不是新增但是被修改过
			// 文件是新增的：看一下有没有历史备份信息
			// 不是新增但是被修改过：有历史信息，但是历史的唯一标识与当前最新的唯一标识不一致
			std::string id;
			// 哈希表有历史信息，不是新增文件
			if (_data->GetOneByKey(filename, &id) != false)
			{
				std::string new_id = GetFileIdentifier(filename);//根据备份目录中的文件获取id
				if (new_id == id) {
					return false;//不需要被上传-上次上传后没有被修改过
				}
			}
			//一个文件比较大,正在徐徐的拷贝到这个目录下，拷贝需要一个过程，
			//如果每次遍历则都会判断标识不一致需要上传一个几十G的文件会上传上百次
			//因此应该判断一个文件一段时间都没有被修改过了，则才能上传
			FileUtil fu(filename);
			if (time(NULL) - fu.LastMTime() < 3) {//3秒钟之内刚修改过--认为文件还在修改中
				return false;
			}
			std::cout << filename << " need upload!\n";
			return true;
		}


		void RunModule()
		{
			while (1)
			{
				//遍历获取备份文件夹中所有文件
				FileUtil fu(_back_dir);
				std::vector<std::string> arry;
				fu.ScanDirectory(&arry);
				//逐个判断文件是否需要上传
				for (auto& a : arry)
				{
					if (IsNeedUpload(a) == false)
					{
						continue;
					}
					//如果需要上传则上传文件
					if (Upload(a) == true)
					{
						_data->Insert(a, GetFileIdentifier(a));//新增文件备份信息
						std::cout << a << " upload success!\n";
					}
				}
				Sleep(1000);
				std::cout << "-------------------------loop end-------------------------\n";
			}
		}
	};
}

#endif